﻿using HK.Core.Common.Data;
using HK.Core.Common.Protocol;
using HK.Core.Common.Protocol.Data;
using HK.Core.Encryption.Protocol;
using HK.Core.Serializable.Data;
using HK.Core.Serializable.Protocol.Data;
using UnityEngine;
using UnityEngine.Rendering;

namespace HK.Core.Settings.Protocol
{

    /// <summary>
    /// 接口 : 环境光设定
    /// </summary>
    public interface IAmbientSettings : IJsonData
    {
        /// <summary>
        /// 光照模式
        /// <para>* Unity 可以提供几种环境光照模式，例如具有独立天空、赤道和地面颜色的方向环境或具有一种颜色的平面环境。</para>
        /// </summary>
        AmbientMode Mode { get; }
        
        /// <summary>
        /// 侧面环境光
        /// <para>* Trilight 环境光照模式使用此颜色影响朝向侧面的对象部分。</para>
        /// <para>* 在平面环境光照模式中，赤道颜色只是单一的环境颜色，并且与 ambientLight 的值相同。</para>
        /// </summary>
        Color EquatorColor { get; }
        
        /// <summary>
        /// 下方环境光
        /// <para>* Trilight 环境光照模式使用此颜色影响朝向下方的对象部分。</para>
        /// </summary>
        Color GroundColor { get; }
        
        /// <summary>
        /// 上方环境光
        /// <para>* Trilight 环境光照模式使用此颜色影响朝向上方的对象部分。</para>
        /// </summary>
        Color SkyColor { get; }
        
        /// <summary>
        /// 平面环境光照颜色
        /// <para>* 平面环境光照模式会使用颜色，其值与 ambientSkyColor 的值相同</para>
        /// </summary>
        Color Light { get; }
        
        /// <summary>
        /// 环境光强度
        /// <para>* 来自环境光源的光照会对场景产生多大的影响</para>
        /// </summary>
        float Intensity { get; }
    }

    /// <summary>
    /// 接口 : 光晕设定
    /// </summary>
    public interface IFlareSettings : IJsonData
    {
        /// <summary>
        /// 光晕的淡化速度
        /// <para>* 场景中所有光晕的淡化速度</para>
        /// </summary>
        float FadeSpeed { get; }
        
        /// <summary>
        /// 光晕强度
        /// <para>* 场景中所有光晕的强度</para>
        /// </summary>
        float Strength { get; }
    }

    /// <summary>
    /// 接口 : 雾效设定
    /// </summary>
    public interface IFogSettings : IJsonData
    {
        /// <summary>
        /// 雾效模式
        /// <para>* 另请参阅：RenderSettings.fogMode、Lighting 窗口。</para>
        /// </summary>
        FogMode Mode { get; }
        
        /// <summary>
        /// 雾效开启标志位
        /// </summary>
        bool Fog { get; }
        
        /// <summary>
        /// 雾效颜色
        /// </summary>
        Color Color { get; }
        
        /// <summary>
        /// 雾效密度
        /// <para>* Exponential 和 ExponentialSquared 模式会使用雾效强度。</para>
        /// </summary>
        float Density { get; }
        
        /// <summary>
        /// 雾效开始距离
        /// <para>* Linear 雾效模式会使用雾效开始和结束距离。</para>
        /// <para>* 另请参阅：RenderSettings.fogEndDistance、RenderSettings.fogMode。</para>
        /// </summary>
        float StartDistance { get; }
        
        /// <summary>
        /// 雾效结束距离
        /// <para>* Linear 雾效模式会使用雾效开始和结束距离。</para>
        /// <para>* 另请参阅：RenderSettings.fogEndDistance、RenderSettings.fogMode。</para>
        /// </summary>
        float EndDistance { get; }
    }

    /// <summary>
    /// 接口 : 反射设定
    /// </summary>
    public interface IReflectionSettings : IJsonData
    {
        /// <summary>
        /// 反射的次数。
        /// <para>* 定义有多少通道计算了反射。在一个给定通道中，场景会渲染到一个立方体贴图中，并将在上个通道中计算的反射应用到反射对象。</para>
        /// <para>* 如果设置为 1，场景将被渲染一次。这意味着反射将不能反射其他反射，并且当在其他反射表面看到反射对象时，反射对象将显示为黑色。</para>
        /// <para>* 如果设置为 2，场景将被渲染两次，并且当在其他反射表面看到反射对象时，反射对象会显示来自第一个通道的反射。</para>
        /// </summary>
        int Bounces { get; }
        
        /// <summary>
        /// 反射强度
        /// <para>* 天空盒/自定义立方体贴图反射会对场景产生多大的影响。</para>
        /// </summary>
        float Intensity { get; }
        
        /// <summary>
        /// 默认反射模式
        /// <para>* Unity 可以使用自定义纹理或从天空盒中生成镜面反射纹理。</para>
        /// </summary>
        DefaultReflectionMode DefaultMode { get; }
    }
    
    /// <summary>
    /// 接口 : 场景渲染设定
    /// <para>* 详情参考 : https://docs.unity3d.com/cn/current/ScriptReference/RenderSettings.html</para>
    /// </summary>
    public interface ISceneRenderSettingsData : IListElement
    {
        /// <summary>
        /// 场景名
        /// </summary>
        string SceneName { get; }
        
#region Ambient

        /// <summary>
        /// 环境光设定
        /// </summary>
        IAmbientSettings AmbientSettings { get; }
        
        /// <summary>
        /// 光照模式
        /// <para>* Unity 可以提供几种环境光照模式，例如具有独立天空、赤道和地面颜色的方向环境或具有一种颜色的平面环境。</para>
        /// </summary>
        AmbientMode AmbientMode { get; }
        
        /// <summary>
        /// 侧面环境光
        /// <para>* Trilight 环境光照模式使用此颜色影响朝向侧面的对象部分。</para>
        /// <para>* 在平面环境光照模式中，赤道颜色只是单一的环境颜色，并且与 ambientLight 的值相同。</para>
        /// </summary>
        Color AmbientEquatorColor { get; }
        
        /// <summary>
        /// 下方环境光
        /// <para>* Trilight 环境光照模式使用此颜色影响朝向下方的对象部分。</para>
        /// </summary>
        Color AmbientGroundColor { get; }
        
        /// <summary>
        /// 上方环境光
        /// <para>* Trilight 环境光照模式使用此颜色影响朝向上方的对象部分。</para>
        /// </summary>
        Color AmbientSkyColor { get; }
        
        /// <summary>
        /// 平面环境光照颜色
        /// <para>* 平面环境光照模式会使用颜色，其值与 ambientSkyColor 的值相同</para>
        /// </summary>
        Color AmbientLight { get; }
        
        /// <summary>
        /// 环境光强度
        /// <para>* 来自环境光源的光照会对场景产生多大的影响</para>
        /// </summary>
        float AmbientIntensity { get; }

#endregion

#region Flare

        /// <summary>
        /// 光晕设定
        /// </summary>
        IFlareSettings FlareSettings { get; }
        
        /// <summary>
        /// 光晕的淡化速度
        /// <para>* 场景中所有光晕的淡化速度</para>
        /// </summary>
        float FlareFadeSpeed { get; }
        
        /// <summary>
        /// 光晕强度
        /// <para>* 场景中所有光晕的强度</para>
        /// </summary>
        float FlareStrength { get; }

#endregion

#region Fog

        /// <summary>
        /// 雾效设定
        /// </summary>
        IFogSettings FogSettings { get; }
        
        /// <summary>
        /// 无效开启标志位
        /// </summary>
        bool Fog { get; }
        
        /// <summary>
        /// 雾效颜色
        /// </summary>
        Color FogColor { get; }
        
        /// <summary>
        /// 雾效强度
        /// <para>* Exponential 和 ExponentialSquared 模式会使用雾效强度。</para>
        /// </summary>
        float FogDensity { get; }
        
        /// <summary>
        /// 雾效模式
        /// <para>* 另请参阅：RenderSettings.fogMode、Lighting 窗口。</para>
        /// </summary>
        FogMode FogMode { get; }
        
        /// <summary>
        /// 雾效开始距离
        /// <para>* Linear 雾效模式会使用雾效开始和结束距离。</para>
        /// <para>* 另请参阅：RenderSettings.fogEndDistance、RenderSettings.fogMode。</para>
        /// </summary>
        float FogStartDistance { get; }
        
        /// <summary>
        /// 雾效结束距离
        /// <para>* Linear 雾效模式会使用雾效开始和结束距离。</para>
        /// <para>* 另请参阅：RenderSettings.fogEndDistance、RenderSettings.fogMode。</para>
        /// </summary>
        float FogEndDistance { get; }

#endregion

#region ReflectionSettings

        /// <summary>
        /// 反射设定
        /// </summary>
        IReflectionSettings ReflectionSettings { get; }
        
        /// <summary>
        /// 默认反射模式
        /// <para>* Unity 可以使用自定义纹理或从天空盒中生成镜面反射纹理。</para>
        /// </summary>
        DefaultReflectionMode DefaultReflectionMode { get; }
        
        /// <summary>
        /// 反射包含其他反射的次数。
        /// <para>* 定义有多少通道计算了反射。在一个给定通道中，场景会渲染到一个立方体贴图中，并将在上个通道中计算的反射应用到反射对象。</para>
        /// <para>* 如果设置为 1，场景将被渲染一次。这意味着反射将不能反射其他反射，并且当在其他反射表面看到反射对象时，反射对象将显示为黑色。</para>
        /// <para>* 如果设置为 2，场景将被渲染两次，并且当在其他反射表面看到反射对象时，反射对象会显示来自第一个通道的反射。</para>
        /// </summary>
        int ReflectionBounces { get; }
        
        /// <summary>
        /// 反射强度
        /// <para>* 天空盒/自定义立方体贴图反射会对场景产生多大的影响。</para>
        /// </summary>
        float ReflectionIntensity { get; }

#endregion
        
        /// <summary>
        /// Light 光环的大小。
        /// <para>* 对于任何光照，光环的大小是此值乘以 Light.range。</para>
        /// </summary>
        float HaloStrength { get; }
        
        /// <summary>
        /// Subtractive 光照模式下太阳阴影使用的颜色
        /// </summary>
        Color SubtractiveShadowColor { get; }
    }
    
    /// <summary>
    /// 接口 : 场景渲染设定列表
    /// </summary>
    /// <typeparam name="TElement">场景渲染设定类型</typeparam>
    public interface ISceneRenderSettingsList<TElement> : IListJsonData<TElement>, IToken, IBinaryEncrypt
        where TElement : JsonData, ISceneRenderSettingsData
    {
        /// <summary>
        /// 保存设定
        /// </summary>
        /// <param name="iSettings">设定信息</param>
        /// <returns>true:OK; false:NG;</returns>
        bool SaveSettings(TElement iSettings);

        /// <summary>
        /// 取得场景设定信息
        /// </summary>
        /// <param name="iSceneName">场景名</param>
        /// <returns>场景设定信息</returns>
        TElement GetSettings(string iSceneName);
    }

    /// <summary>
    /// 接口 : 场景渲染设定
    /// </summary>
    public interface ISceneRenderSettings<TElement>
        where TElement : JsonData, ISceneRenderSettingsData
    {
        /// <summary>
        /// 保存设定
        /// </summary>
        /// <param name="iSettings">设定信息</param>
        /// <returns>true:OK; false:NG;</returns>
        bool SaveSettings(TElement iSettings);

        /// <summary>
        /// 取得场景设定信息
        /// </summary>
        /// <param name="iSceneName">场景名</param>
        /// <returns>场景设定信息</returns>
        TElement GetSettings(string iSceneName);
    }
}
